package com.eascs.web.o2o.web.aging.service.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.eascs.app.log.Logger;
import com.eascs.app.log.LoggerFactory;
import com.eascs.report.common.entity.ModelResult;
import com.eascs.web.o2o.web.aging.dao.ProcessTaskMainDao;
import com.eascs.web.o2o.web.aging.dao.ProcessTaskNodeDao;
import com.eascs.web.o2o.web.aging.dao.TaskNodeAuditorDao;
import com.eascs.web.o2o.web.aging.entity.ProcessTaskMain;
import com.eascs.web.o2o.web.aging.entity.ProcessTaskNode;
import com.eascs.web.o2o.web.aging.entity.TaskNodeAuditor;
import com.eascs.web.o2o.web.aging.service.WFQueryService;


@Service
public class WFQueryServiceImpl implements WFQueryService {
	private static final Logger logger = LoggerFactory.getLogger(WFQueryServiceImpl.class);
	@Autowired
	private ProcessTaskMainDao processTaskMainDao;

	@Autowired
	private ProcessTaskNodeDao processTaskNodeDao;

	@Autowired
	private TaskNodeAuditorDao taskNodeAuditorDao;

	/*@Autowired
	private ProcessNodeTemplateDao processNodeTemplateDao;

	@Autowired
	private ProcessProvinceDao processprovinceDao;
	@Autowired
	private DicDataServiceInlet dicDataServiceInlet;
	@Autowired
	private OrgInletService orgInletService;*/

/*	@Override
	public ModelResult<ProcessNodeTemplate> queryNodeTemplateById(String nodeId) {
		ModelResult<ProcessNodeTemplate> result = new ModelResult<>();
		try {
			result.withModel(processNodeTemplateDao.getById(ProcessNodeTemplate.class, nodeId));
		} catch (Exception e) {
			logger.error("查询流程节点失败", e.getMessage());
			result.withError("WFQueryServiceImpl.queryNodeTemplateById", "查询流程节点失败:" + e.getMessage());
			e.printStackTrace();
		}
		return result;
	}

	@Override
	public ModelResult<PageResult<UserTaskVo>> queryUserTaskByPage(UserTaskParam param) {
		ModelResult<PageResult<UserTaskVo>> result = new ModelResult<>();
		try {
			if (UserTaskParam.APPROVAL_STATUS_UNDO.equals(param.getApprovalStatus())) {
				result.withModel(processTaskMainDao.queryUndoTaskPage(param));
			}
			if (UserTaskParam.APPROVAL_STATUS_FINISH.equals(param.getApprovalStatus())) {
				result.withModel(processTaskMainDao.queryHasdoTaskPage(param));
			}
			if (UserTaskParam.APPROVAL_STATUS_PROCESSING.equals(param.getApprovalStatus())) {
				result.withModel(processTaskMainDao.queryAppliedbyTaskPage(param));
			}
		} catch (Exception e) {
			logger.error("查询审批任务列表失败", e.getMessage());
			result.withError("WFQueryServiceImpl.queryUserTaskByPage", "查询审批任务列表失败:" + e.getMessage());
			e.printStackTrace();
		}
		return result;
	}

	@Override
	public ModelResult<NodeApprovalVo> queryApprovalInfo(User user, String nodeAuditorId) {
		ModelResult<NodeApprovalVo> result = new ModelResult<>();
		try {
			NodeApprovalVo nodeApprovalVo = new NodeApprovalVo();
			TaskNodeAuditor auditor = taskNodeAuditorDao.getById(TaskNodeAuditor.class, nodeAuditorId);
			ProcessTaskNode taskNode = processTaskNodeDao.getById(ProcessTaskNode.class, auditor.getTaskNodeId());
			ProcessTaskMain processTaskMain = processTaskMainDao.getById(ProcessTaskMain.class, taskNode.getTaskId());
			nodeApprovalVo.setProcessTaskMain(processTaskMain);
			nodeApprovalVo.setProcessTaskNode(taskNode);
			nodeApprovalVo.setAuditor(auditor);
			// 当前审批流程实例
			logger.info("获取流程审批节点信息，用户:{},节点处理人ID:", user.getAccount(), nodeAuditorId);
			if (user.isSuperAdministrator()) {
				nodeApprovalVo.setCanLook(true);
				// 超管可以审批正在审核中的节点
				if (taskNode.getNodeStatus() == ProcessTaskNode.NODE_STATUS_AUDITING) {
					nodeApprovalVo.setAuditor(auditor);
					// 是否拥有当前节点审批权限
					if (auditor.getAuditorStatus() == TaskNodeAuditor.AUDITOR_STATUS_AUDITING) {
						nodeApprovalVo.setCanApproval(true);
					}
				}
			}
			if (user.getNo().equals(auditor.getAuditorNo())) {
				// 节点审核人
				nodeApprovalVo.setAuditor(auditor);
				// 查看审批意见权限
				nodeApprovalVo.setCanLook(true);
				// 是否拥有当前节点审批权限
				if (auditor.getAuditorStatus() == TaskNodeAuditor.AUDITOR_STATUS_AUDITING) {
					nodeApprovalVo.setCanApproval(true);
				}
			}
			if (nodeApprovalVo.isCanApproval()) {
				// 获取当前处理节点和节点模板
				if (taskNode.getNodeStatus() == ProcessTaskNode.NODE_STATUS_AUDITING) {
					nodeApprovalVo.setProcessTaskNode(taskNode);
					ProcessNodeTemplate nodeTemplate = processNodeTemplateDao.getById(ProcessNodeTemplate.class,
							taskNode.getNodeTemplateId());
					nodeApprovalVo.setProcessNodeTemplate(nodeTemplate);
				}
			}
			if (nodeApprovalVo.isCanLook()) {
				logger.info("当前用户没有经办权限, account:{}, 节点处理人ID:{}", user.getAccount(), nodeAuditorId);
				result.withError("WFQueryService.queryApprovalInfo", "当前用户没有经办权限");
			}
			// 查询加签类型
			if (StringUtils.isNotBlank(taskNode.getSignType())) {
				String[] signTypeArr = StringUtils.split(taskNode.getSignType(), ",");
				List<String> signTypeList = Arrays.asList(signTypeArr);
				ModelResult<List<DicData>> modelResult = dicDataServiceInlet.getDicDataByTypeAndKeys("SIGN_TYPE",
						signTypeList);
				nodeApprovalVo.setSignTypeList(modelResult.getModel());
			}
			result.withModel(nodeApprovalVo);
		} catch (Exception e) {
			logger.error("查询用户当前流程节点信息失败, account:{}, 节点处理人ID:{}", user.getAccount(), nodeAuditorId);
			result.withError("WFQueryService.queryApprovalInfo", "查询用户当前流程节点信息失败");
			e.printStackTrace();
			return result;
		}
		return result;
	}

	public ModelResult<List<ProcessTaskMain>> queryAgreeList(String referId) {
		ModelResult<List<ProcessTaskMain>> modelResult = new ModelResult<>();
		// 获取每个流程实例当前主流程
		List<ProcessTaskMain> taskMainTypeList = processTaskMainDao.getTaskMainTypeListByReferId(referId);
		for (int i = 0; i < taskMainTypeList.size(); i++) {
			ProcessTaskMain typeMain = taskMainTypeList.get(i);
			List<ProcessTaskMain> taskMainList = processTaskMainDao.getTaskMainListByType(referId,
					typeMain.getProcessType());
			taskMainTypeList.set(i, getMainProcess(taskMainList));
		}
		modelResult.withModel(taskMainTypeList);
		return modelResult;
	}

	public ModelResult<ProcessTaskMain> queryAgreeDetail(String referId, String processType) {
		ModelResult<ProcessTaskMain> modelResult = new ModelResult<>();
		// 获取单据号下所有流程类型
		List<ProcessTaskMain> taskMainList = processTaskMainDao.getTaskMainListByType(referId, processType);
		if (taskMainList == null || taskMainList.size() == 0) {
			logger.info("贷款单号：[{}] 下没有流程类型未：[{}]的实例！", referId, processType);
			return new ModelResult<ProcessTaskMain>("taskmain.isnull", "流程不存在");
		}
		ProcessTaskMain processTaskMain = getMainProcess(taskMainList);
		if (processTaskMain == null) {
			return new ModelResult<ProcessTaskMain>("taskmain.isnull", "流程不存在");
		}
		List<ProcessTaskNode> taskNodeListShow = new ArrayList<>();
		// 查找每个流程类型的所有流程实例，合并节点审批意见
		for (ProcessTaskMain taskMain : taskMainList) {
			List<ProcessTaskNode> taskNodeList = processTaskNodeDao.getTaskApprovalNodeList(referId,
					taskMain.getProcessId(), taskMain.getTaskId());
			// 查询每个节点的节点处理人
			for (ProcessTaskNode taskNode : taskNodeList) {
				List<TaskNodeAuditor> auditors = taskNodeAuditorDao.getNodeAuditors(taskNode.getTaskNodeId());
				// 移除已办结点中非经办人的信息
				if (ProcessTaskNode.NODE_STATUS_AUDIT_PASS == taskNode.getNodeStatus()
						|| ProcessTaskNode.NODE_STATUS_TURNED_DOWN == taskNode.getNodeStatus()) {
					Iterator<TaskNodeAuditor> iterator = auditors.iterator();
					while (iterator.hasNext()) {
						TaskNodeAuditor auditor = iterator.next();
						if (StringUtils.isBlank(auditor.getAuditNotes())) {// 没有审核意见的移除掉
							iterator.remove();
						}
					}
				}
				if (auditors != null && auditors.size() > 0) {
					taskNode.setAuditors(auditors);
				}
				// 驳回之后待审批的节点不显示
				if (ProcessTaskMain.PROECESS_STATUS_TURNED_DOWN == taskMain.getProcessStatus()
						&& ProcessTaskNode.NODE_STATUS_PENDING_AUDIT == taskNode.getNodeStatus()) {
					continue;
				}
				taskNodeListShow.add(taskNode);
			}
		}
		processTaskMain.setTaskNodeList(taskNodeListShow);
		modelResult.withModel(processTaskMain);
		return modelResult;
	}

	

	// 如果一个类型的流程启动了多个实例，则需获取其中的主流程，优先取正在审批中的流程
	private static ProcessTaskMain getMainProcess(List<ProcessTaskMain> taskMainList) {
		if (taskMainList.size() == 1)
			return taskMainList.get(0);
		if (taskMainList.size() > 1) {
			for (ProcessTaskMain taskMain : taskMainList) {
				if (taskMain.getProcessStatus() == ProcessTaskMain.PROECESS_STATUS_HANDING) {
					return taskMain;
				}
			}
			for (ProcessTaskMain taskMain : taskMainList) {
				if (taskMain.getProcessStatus() != ProcessTaskMain.PROECESS_STATUS_TURNED_DOWN) {
					return taskMain;
				}
			}
			return taskMainList.get(0);
		}
		return null;
	}

	@Override
	public ModelResult<ProcessTaskMain> queryTaskMainById(String taskId) {
		ModelResult<ProcessTaskMain> result = new ModelResult<>();
		result.withModel(processTaskMainDao.getById(ProcessTaskMain.class, taskId));
		return result;
	}

	@Override
	public ModelResult<String> queryReferIdByNodeAuditorId(String nodeAuditorId) {
		ModelResult<String> result = new ModelResult<>();
		result.withModel(processTaskMainDao.queryReferIdByNodeAuditorId(nodeAuditorId));
		return result;
	}

	@Override
	public ModelResult<String> queryTaskIdByNodeAuditorId(String nodeAuditorId) {
		ModelResult<String> result = new ModelResult<>();
		result.withModel(processTaskMainDao.queryTaskIdByNodeAuditorId(nodeAuditorId));
		return result;
	}

	@Override
	public ModelResult<PageResult<ProcessTimeVo>> queryProcessTimes(ProcessTimeParam param) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		logger.info("queryProcessTimes.start...");
		String appliedDateFormat = "";
		if (param.getAppliedDate() != null) {
			appliedDateFormat = sdf.format(param.getAppliedDate());
		}
		logger.info("ProcessTimeParam appliedDate:" + appliedDateFormat + ",size:" + param.getPageSize() + ",index:"
				+ param.getPageIndex());
		ModelResult<PageResult<ProcessTimeVo>> result = new ModelResult<>();
		PageResult<ProcessTimeVo> pageResult = processTaskMainDao.queryProcessLoanPage(param);
		logger.info("ProcessTimeParam pageResult DbRowCount:" + pageResult.getDbRowCount());
		if (pageResult.getDbRowCount() > 0) {
			List<ProcessTimeVo> dataList = pageResult.getData();
			logger.info("ProcessTimeParam pageResult dataList size:" + dataList.size());
			for (ProcessTimeVo obj : dataList) {
				logger.info("------ProcessTimeParam dataList foreach referid:" + obj.getLoanapplyNo());
				List<ProcessTaskMain> list = processTaskMainDao.getTaskMainListByReferId(obj.getLoanapplyNo());
				for (ProcessTaskMain taskMain : list) {
					if (ProcessTemplate.PROECESS_TYPE_CREDIT.equals(taskMain.getProcessType())) {
						obj.setCreditStartTime(taskMain.getAuditorStime());
						obj.setCreditEndTime(taskMain.getAuditorEtime());
					}
					if (ProcessTemplate.PROECESS_TYPE_INAUDIT.equals(taskMain.getProcessType())) {
						obj.setInauditStartTime(taskMain.getAuditorStime());
						obj.setInauditEndTime(taskMain.getAuditorEtime());
					}
					if (ProcessTemplate.PROECESS_TYPE_BANK_REPORT.equals(taskMain.getProcessType())) {
						obj.setBankReportEndTime(taskMain.getAuditorEtime());
					}
					String auditorStime = "";
					String auditorEtime = "";
					if (taskMain.getAuditorStime() != null) {
						auditorStime = sdf.format(taskMain.getAuditorStime());
					}
					if (taskMain.getAuditorEtime() != null) {
						auditorEtime = sdf.format(taskMain.getAuditorEtime());
					}
					logger.info("---ProcessTimeParam item foreach type:[{}],AuditorStime:[{}],AuditorEtime[{}]",
							taskMain.getProcessType(), auditorStime, auditorEtime);
				}
			}
			pageResult.setData(dataList);
		}
		logger.info("ProcessTimeParam result size:" + pageResult.getData().size());
		result.withModel(pageResult);
		return result;
	}

	@Override
	public Map<String, List<WorkWarnEntity>> queryWorkWarnList() {
		List<WorkWarnEntity> list = taskNodeAuditorDao.queryWorkWarnList();
		if (list.size() > 0) {
			Map<String, List<WorkWarnEntity>> map = new HashMap<>();
			for (WorkWarnEntity w : list) {
				if (StringUtils.isBlank(w.getEmail())) {
					logger.info("wfWorkWarn.querylist.notEmail object:{}", w.toString());
					continue;
				}
				List<WorkWarnEntity> value = map.get(w.getEmail());
				if (value == null) {
					value = new ArrayList<>();
					map.put(w.getEmail(), value);
				}
				value.add(w);
			}
			return map;
		}
		return null;
	}

	// 根据平台编号查询省区名称
	@Override
	public ModelResult<String> getProvincebyUNITNO(String unitno) {
		ModelResult<String> result = new ModelResult<>();
		if (StringUtils.isBlank(unitno)) {
			return result;
		}
		result.withModel(processprovinceDao.getProvince(unitno));
		return result;
	}

	@Override
	public List<SignTypeExportVo> getYHSBSCNodeSignType(String provinceCode, String sDate, String eDate) {
		List<SignTypeExportVo> exportResult = new ArrayList<SignTypeExportVo>();
		// 银行申报审查节点
		List<Object[]> taskMainList = processTaskMainDao.getTaskMainByNodeCode("mq03", provinceCode, sDate, eDate);
		for (Object[] objArr : taskMainList) {
			SignTypeExportVo exportVo = new SignTypeExportVo();
			exportVo.setLoanNo((String) objArr[0]);
			exportVo.setProvinceName((String) objArr[1]);
			exportVo.setUnitName((String) objArr[2]);
			exportVo.setCreditManager((String) objArr[3]);
			exportVo.setNodeName((String) objArr[4]);
			String nodeId = (String) objArr[5];
			List<TaskNodeAuditor> auditorList = taskNodeAuditorDao.getSignNodeAuditor(nodeId);
			if (!CollectionUtils.isEmpty(auditorList)) {
				exportVo.setIsSign("Y");
				Set<String> signTypeSet = new HashSet<String>();
				for (TaskNodeAuditor auditor : auditorList) {
					String signType = auditor.getSignType();
					if (StringUtils.isNotBlank(signType)) {
						List signTypeList = CollectionUtils.arrayToList(StringUtils.split(signType, ","));
						signTypeSet.addAll(signTypeList);
					}
				}
				if (!CollectionUtils.isEmpty(signTypeSet)) {
					exportVo.assigSignType(signTypeSet);
				}
			}
			exportResult.add(exportVo);
		}
		return exportResult;
	}

	@Override
	public ProcessTaskNode getTaskNodeDetail(String referId, String processType, String nodeCode) {
		return processTaskNodeDao.getTaskNodeDetail(referId, processType, nodeCode);
	}

	@Override
	public void updateTaskNodeStartDate() {
		List<ProcessTaskNode> nodeList = processTaskNodeDao.findEntitys(
				"SELECT * from wf_process_task_node t where t.auditor_end_date < t.auditor_start_date",
				ProcessTaskNode.class);
		for (ProcessTaskNode node : nodeList) {
			String taskId = node.getTaskId();
			int nodeSeq = node.getNodeSeq() - 1;
			ProcessTaskNode nodeTmp = processTaskNodeDao.getTaskNodeByTaskIdAndNodeSeq(taskId, nodeSeq);
			if (nodeTmp != null && nodeTmp.getAuditorEndDate() != null) {
				processTaskNodeDao.updateTaskNodeStartDate(node.getTaskNodeId(), nodeTmp.getAuditorEndDate());
			}
		}
	}*/
	
	@Override
	public ModelResult<ProcessTaskMain> queryAgreeDetailWithTaskId(String taskId) {
		ModelResult<ProcessTaskMain> modelResult = new ModelResult<>();
		// 获取单据号下所有流程类型
		ProcessTaskMain taskMain = processTaskMainDao.getById(ProcessTaskMain.class, taskId);
		List<ProcessTaskNode> taskNodeListShow = new ArrayList<>();
		// 查找每个流程类型的所有流程实例，合并节点审批意见
		List<ProcessTaskNode> taskNodeList = processTaskNodeDao.getNodeListByTaskId(taskId);
		// 查询每个节点的节点处理人
		for (ProcessTaskNode taskNode : taskNodeList) {
			List<TaskNodeAuditor> auditors = taskNodeAuditorDao.getNodeAuditors(taskNode.getTaskNodeId());
			// 移除已办结点中非经办人的信息
			if (ProcessTaskNode.NODE_STATUS_AUDIT_PASS == taskNode.getNodeStatus()
					|| ProcessTaskNode.NODE_STATUS_TURNED_DOWN == taskNode.getNodeStatus()) {
				Iterator<TaskNodeAuditor> iterator = auditors.iterator();
				while (iterator.hasNext()) {
					TaskNodeAuditor auditor = iterator.next();
					if (StringUtils.isBlank(auditor.getAuditNotes())) {// 没有审核意见的移除掉
						iterator.remove();
					}
				}
			}
			if (auditors != null && auditors.size() > 0) {
				taskNode.setAuditors(auditors);
			}
			// 驳回之后待审批的节点不显示
			if (ProcessTaskMain.PROECESS_STATUS_TURNED_DOWN == taskMain.getProcessStatus()
					&& ProcessTaskNode.NODE_STATUS_PENDING_AUDIT == taskNode.getNodeStatus()) {
				continue;
			}
			taskNodeListShow.add(taskNode);
		}
		taskMain.setTaskNodeList(taskNodeListShow);
		modelResult.withModel(taskMain);
		return modelResult;
	}
}
